home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 3 code / Surf's Up! / CSurfer / Surfer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-14  |  40.2 KB  |  1,663 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    Apple Products Presents
  4. #
  5. #    S U R F E R    ----- A CommToolbox Sample Application
  6. #        by Alex Kazim
  7. #
  8. #    Based on the MacDTS Simple Sample Application
  9. #
  10. #    Surfer.c    -    C Source
  11. #
  12. #    Copyright © 1988-9 Apple Computer, Inc.
  13. #    All rights reserved.
  14. #
  15. #    Versions:    Sample 1.0                    08/88
  16. #                Sample 1.01                    11/88
  17. #
  18. #                Surfer 1.0                    10/89
  19. #                Surfer 1.01                    02/90
  20. ------------------------------------------------------------------------------*/
  21.  
  22. /*
  23. REVISION HISTORY
  24.  
  25.     9/26/89        kaz        • changed case on constants to match documentation
  26.                         • Fixed error handling to only call xxEvent() if the
  27.                         target of the event is a tool window
  28.                         • Initializes gBuffer according to sizes[cmDataIn]
  29.                         after the _CMNew call
  30.                         
  31.     10/1/89        kaz        • TermGetConnEnvirons() and FTGetConnEnvirons() were
  32.                         merged into one routine: ToolGetConnEnvirons()
  33.                         • IsAppWindow() uses _GetWRefCon instead of looking
  34.                         at the windowrecord refcon field.
  35.                         • Moved DiposePtr(gBuffer) to CloseWindow()
  36.                         • _HLock/_HUnlock all the tool handles
  37.                         • Took out alerts to let the tools handle it themselves
  38.                         
  39.     10/4/89        kaz        • Was forgetting to clear gStartFT after a receive
  40.                                 
  41.     1/9/90        kaz        • Fixed a bug that didn't call _TMIdle if there was
  42.                         a same-circuit file transfer in progress.  _TMIdle
  43.                         will be called regardless.
  44.                         • TermSendProc() will not send any data if there is 
  45.                         a same-circuit file transfer in progress.
  46.                         
  47.     1/29/90        kaz        • Allocates the buffer by looking at the bufSizes in
  48.                         the ConnRecord instead of assuming my Buffer max.
  49.                         • Cleaned up TermRecvProc() to be less confusing
  50.                         
  51.     2/14/90        kaz        • Was _HLocking the term handle before _TMChoose instead
  52.                         of _HUnlocking it.
  53.                         
  54.     8/7/92        cnc        • Ported to C from Pascal
  55. */
  56.  
  57.  
  58. #include <CommResources.h>
  59. #include <Terminals.h>
  60. #include <Connections.h>
  61. #include <FileTransfers.h>
  62. #include <Types.h>
  63. #include <Errors.h>
  64. #include <Windows.h>
  65. #include <Fonts.h>
  66. #include <Menus.h>
  67. #include <Memory.h>
  68. #include <Desk.h>
  69. #include <DiskInit.h>
  70. #include <ToolUtils.h>
  71. #include <QuickDraw.h>
  72.  
  73. #include "Surfer.h"
  74.  
  75. #ifndef FALSE
  76. #define FALSE    0
  77. #define TRUE    1
  78. #endif
  79.  
  80. const     Str32    kDefaultTermTool    = "\pVT102 Tool";        // what tools we want first        
  81. const     Str32    kDefaultFTTool        = "\pText Tool";
  82. const     Str32    kDefaultConnTool    = "\pSerial Tool";
  83.  
  84. Boolean        gHasWaitNextEvent;    //set up by Initialize
  85. Boolean        gInBackground;        //maintained by Initialize and DoEvent    
  86.     
  87. TermHandle    gTerm;                // Tool Handles: Single Session            
  88. ConnHandle    gConn;
  89. FTHandle    gFT;
  90.  
  91. Ptr    gBuffer;                    // Data Storage for Reads/Writes            
  92.     
  93. long    gFTSearchRefNum;        // Auto-Initiate File Transfers            
  94. Boolean    gStartFT;                // Auto-start                            
  95. Boolean    gWasFT;                    // In progress                            
  96.     
  97.     
  98. pascal void AlertUser(Str255 msg, Boolean fatal);
  99. pascal void Terminate(void);
  100.  
  101. /*******************************************************************
  102. *    TrapAvailable    - Checks to see if a given trap is implemented
  103. *
  104. *        tNumber        - trap number
  105. *        tType        - type of trap
  106. *
  107. *        returns        - true if it exists
  108. *
  109. **********************************************************************/
  110. #pragma segment Initialize
  111. pascal Boolean TrapAvailable(short tNumber, TrapType tType)
  112. {
  113.     short unImplemented;
  114.     
  115.     if (tType == OSTrap)
  116.         unImplemented = _UnimplementedOSTrap;
  117.     else
  118.         unImplemented = _UnimplementedToolTrap;
  119.  
  120.     return NGetTrapAddress(tNumber, tType) != GetTrapAddress(unImplemented);
  121. } //TrapAvailable
  122.  
  123.  
  124. /*******************************************************************
  125. *    TermSendProc    - Sends the data out the connection
  126. *
  127. *        thePtr        - the data to send
  128. *        theSize        - bytes to send
  129. *        refcon        - terminal tool refcon
  130. *        flags        - connection flags
  131. *
  132. *        returns        - bytes sent
  133. *
  134. **********************************************************************/
  135. #pragma segment Main
  136. pascal long TermSendProc(Ptr thePtr,long theSize, long refcon, short flags)
  137. {
  138. #pragma unused (refcon)
  139.  
  140.     OSErr    theErr;
  141.     long    retCode = 0;                        // Assume the worst            
  142.     
  143.     if (gConn != NULL) 
  144.     {
  145.     
  146.         // If there's a file transfer in progress && it's     
  147.         // over our connection, then don't send the data.    
  148.         
  149.         if (gFT != NULL) 
  150.         {
  151.             if (((((*gFT)->flags) & ftIsFTMode) != 0) &&
  152.                 ((((*gFT)->attributes) & ftSameCircuit) != 0))
  153.                 return retCode;
  154.         }
  155.         
  156.         theErr = CMWrite(gConn, thePtr, &theSize, cmData, FALSE, NULL, 0, flags);
  157.                             
  158.         if (theErr == noErr)
  159.             retCode = theSize;        // If ok, we sent all        
  160.         
  161.     } // Good Connection    
  162.     
  163.     return retCode;
  164. } // TermSendProc        
  165.  
  166.  
  167. /*******************************************************************
  168. *    TermRecvProc    - Gets the data from the connection and sends 
  169. *                    it to the terminal tool.
  170. *
  171. *        NOTE        - This is !a callback proc, but does 
  172. *                    resemble the functionality.
  173. *
  174. *
  175. **********************************************************************/
  176. #pragma segment Main
  177. pascal void TermRecvProc(void)
  178. {
  179.     CMErr            theErr;
  180.     CMStatFlags        status;
  181.     CMBufferSizes    sizes;
  182.     CMFlags            flags;
  183.     long            bytesEaten;
  184.     
  185.     if ((gConn != NULL) && (gTerm != NULL)) 
  186.     {
  187.     
  188.         // Get the state of the connection    
  189.         theErr = CMStatus(gConn, sizes, &status);
  190.         
  191.         if (theErr == noErr)  
  192.         {
  193.         
  194.             // Route the data if we have any            
  195.             if ((((status & cmStatusOpen)+ cmStatusDataAvail) != 0) &&  
  196.                 (sizes[cmDataIn] != 0)) 
  197.             {
  198.                 
  199.                 // Tell the tool to get the data    
  200.                 theErr = CMRead(gConn, gBuffer, &sizes[cmDataIn], cmData, FALSE, 
  201.                                 NULL, 0, &flags);
  202.                 
  203.                 // Send data to the terminal    
  204.                 if (theErr == noErr)
  205.                     bytesEaten = TMStream(gTerm,gBuffer, sizes[cmDataIn],flags);
  206.                                             
  207.                 // Could check bytesEaten vs. sizes[cmDataIn]    
  208.                                             
  209.             } // sizes != 0    
  210.                 
  211.         } // Good Status        
  212.         
  213.         if (theErr != noErr)
  214.             ;        // Connection tool will alert the user on an error    
  215.         
  216.     } // Good term && conn    
  217.     
  218. } // TermRecvProc        
  219.  
  220.  
  221.  
  222. /*******************************************************************
  223. *    ToolGetConnEnvirons    - Gets the connection environs for
  224. *                        the FT or Term tool
  225. *
  226. *        refcon            - the tool refcon
  227. *        theEnvirons        - the environment
  228. *
  229. *        returns            - an environment error
  230. *
  231. **********************************************************************/
  232. #pragma segment Main
  233. pascal OSErr ToolGetConnEnvirons(long refcon, ConnEnvironRec *theEnvirons)
  234. {
  235. #pragma unused (refcon)
  236.  
  237.     OSErr retCode = envNotPresent;        // pessimism         
  238.     
  239.     // Version is set by the tool    
  240.     if (gConn != NULL)
  241.         retCode = CMGetConnEnvirons(gConn, theEnvirons);
  242.     
  243.     return retCode;
  244. } // TermGetConnEnvirons    
  245.  
  246.  
  247.  
  248. /*******************************************************************
  249. *    FTSendProc    - Sends data during a file transfer
  250. *
  251. *        thePtr        - data to send
  252. *        theSize        - bytes to send
  253. *        refcon        - the FTtool refcon
  254. *        channel        - which channel to use
  255. *        flags        - connection flags
  256. *
  257. *        returns        - bytes sent
  258. *
  259. **********************************************************************/
  260. #pragma segment Main
  261. pascal long FTSendProc(thePtr, theSize, refcon, channel, flags)
  262.     Ptr         thePtr;
  263.     long         theSize;
  264.     long        refcon;
  265.     CMChannel    channel;
  266.     short        flags;
  267. {
  268. #pragma unused (refcon)
  269.  
  270.     CMErr    theErr;
  271.     long    retCode = 0;                    // Assume the worst        
  272.     
  273.     if (gConn != NULL) {
  274.                                         // Send the data            
  275.         theErr = CMWrite(gConn, thePtr, &theSize, channel, FALSE, NULL, 0, flags);
  276.         if (theErr == noErr)
  277.             retCode = theSize;        // if ok, we sent all    
  278.  
  279.     } // Good Connection    
  280.     
  281.     return retCode;
  282. } // FTSendProc    
  283.  
  284.  
  285.  
  286. /*******************************************************************
  287. *    FTReceiveProc    - Gets data during a file transfer
  288. *
  289. *        thePtr        - place for data
  290. *        theSize        - bytes to get
  291. *        refcon        - the FTtool refcon
  292. *        channel        - which channel to use
  293. *        flags        - connection flags
  294. *
  295. *        returns        - bytes gotten
  296. *
  297. **********************************************************************/
  298. #pragma segment Main
  299. pascal long FTReceiveProc(thePtr, theSize, refcon, channel, flags)
  300.     Ptr         thePtr;
  301.     long        theSize;
  302.     long        refcon;
  303.     CMChannel    channel;
  304.     CMFlags        *flags;
  305. {
  306. #pragma unused (refcon)
  307.  
  308.     CMErr    theErr;
  309.     long    retCode = 0;                    // Assume the worst        
  310.     
  311.     if (gConn != NULL) 
  312.     {
  313.         // Read all the data        
  314.         theErr = CMRead(gConn, thePtr, &theSize, channel, FALSE, NULL, 0, flags);
  315.         if (theErr == noErr)
  316.             retCode = theSize;    // if ok, we got all        
  317.  
  318.     } // Good Connection    
  319.     
  320.     return retCode;
  321. } // FTReceiveProc    
  322.  
  323.  
  324. /*******************************************************************
  325. *    AutoRecCallback    - Sets the file transfer flag if an auto-
  326. *                    receive string was found.
  327. *
  328. *        theConn            - which connection tool found it
  329. *        data            - ptr to last character in the match
  330. *        refNum            - which search was found
  331. *
  332. **********************************************************************/
  333. #pragma segment Main
  334. pascal void AutoRecCallback(ConnHandle theConn, Ptr data, long refNum)
  335. {
  336. #pragma unused (theConn, data)
  337.  
  338.     // We can't call _FTStart or _CMRemoveSearch here as     
  339.     // this proc might be called from Interrupt level        
  340.     
  341.     if (gFTSearchRefNum == refNum)
  342.         gStartFT = TRUE;        // Set the flag to call FTStart in Idle    
  343. } // AutoRecCallBack    
  344.  
  345.  
  346.  
  347. /*******************************************************************
  348. *    AddFTSearch        - Checks to see if the file transfer has an
  349. *                    auto-receive string, and adds a search to 
  350. *                    find it.
  351. *
  352. **********************************************************************/
  353. #pragma segment Main
  354. pascal void AddFTSearch(void)
  355. {    
  356.     Str255    tempStr;    // the string to look for
  357.     
  358.     if ((gFT != NULL) && (gConn != NULL)) 
  359.     {
  360.         if ((*gFT)->autoRec[0]) // Do I need to add a search
  361.         {
  362.             BlockMove((*gFT)->autoRec, tempStr, (*gFT)->autoRec[0] + 1);                
  363.             gFTSearchRefNum = CMAddSearch(gConn, tempStr, cmSearchSevenBit, &AutoRecCallback);
  364.             if (gFTSearchRefNum == -1) 
  365.             {
  366.                 AlertUser("\pCouldn't add stream search",FALSE);
  367.                 gFTSearchRefNum = 0;
  368.             }
  369.         } // can autoreceive    
  370.         
  371.     } // good FT and Conn    
  372.     
  373. } // AddFTSearch        
  374.  
  375.  
  376.  
  377. /*******************************************************************
  378. *    DoSend    - Initiates a File Transfer send from the menu command
  379. *
  380. **********************************************************************/
  381. #pragma segment Main
  382. pascal void DoSend(void)
  383. {
  384.     SFReply        theReply;            // File Info                    
  385.     Point        where;                // Top Left of File dialog    
  386.     short        numTypes;            // File Types to display        
  387.     SFTypeList    typeList;
  388.     FTErr        anyErr;                // Error handler                
  389.  
  390.     if (gFT != NULL) 
  391.     {
  392.         SetPt(&where, 100, 100);
  393.         
  394.         // If the FT tool can only send Text files, then            
  395.         // only display text files, else display all types        
  396.     
  397.         // Check to see if Text Only flag is set    
  398.         if ((((*gFT)->attributes) & ftTextOnly) != 0) 
  399.         {
  400.             typeList[0] = 'TEXT';
  401.             numTypes = 1;
  402.         }        
  403.         else
  404.             numTypes = -1;
  405.             
  406.         SFGetFile(where, "\pFile to Send", NULL, numTypes, typeList, NULL, &theReply);
  407.         
  408.         // Did the user hit OK or Cancel    
  409.         if (theReply.good) 
  410.         {
  411.             // Transfer the file TO the remote    
  412.             anyErr = FTStart(gFT, ftTransmitting, &theReply);
  413.             
  414.             if (anyErr != noErr)
  415.                 ;            // File Transfer tool will alert user on an error    
  416.                 
  417.         } // Good file    
  418.     } // Good FTHandle    
  419.     
  420. } // DoSend    
  421.  
  422.  
  423. /*******************************************************************
  424. *    DoReceive    - Initiates a File Transfer receive from the menu
  425. *
  426. **********************************************************************/
  427. #pragma segment Main
  428. pascal void DoReceive(void)
  429. {
  430.     SFReply    theReply;        // File Info            
  431.     OSErr    anyErr;            // Errors on Start    
  432.     
  433.     if (gFT != NULL) 
  434.     {
  435.         
  436.         // Let the FT tool use its own default file info    
  437.         theReply.vRefNum = 0;
  438.         theReply.fName[0] = 0;
  439.         theReply.good = TRUE;
  440.         
  441.         gStartFT = FALSE;        // Shut the flag down            
  442.         
  443.         // We remove the search temporarily in case it comes        
  444.         // across during the transfer. Will be re-added in the    
  445.         // idle loop once the transfer is completed                
  446.         
  447.         if (gConn != NULL)
  448.             if (((*gFT)->autoRec[0] != 0) && (gFTSearchRefNum != 0)) 
  449.             {
  450.                 CMRemoveSearch(gConn, gFTSearchRefNum);
  451.                 gFTSearchRefNum = 0;    // We found it already    
  452.             }
  453.         
  454.         // Start receiving the file                        
  455.         // The rest gets transferred in the Idle loop    
  456.         
  457.         anyErr = FTStart(gFT, ftReceiving, &theReply);
  458.         
  459.         if (anyErr != noErr)
  460.             ;            // File Transfer tool will alert user on an error    
  461.             
  462.     } // Good Handle    
  463.     
  464. } // DoReceive    
  465.  
  466.  
  467. /*******************************************************************
  468. *    IsDAWindow    - Checks to see if a window belongs to a desk acc.
  469. *
  470. *        window        - the culprit
  471. *
  472. *        returns        - true if it's a DA
  473. *
  474. **********************************************************************/
  475. #pragma segment Main
  476. pascal Boolean IsDAWindow(WindowPtr window)
  477. {
  478.     if (window == NULL)
  479.         return FALSE;
  480.     else    // DA windows have negative windowKinds
  481.         return ((WindowPeek) window)->windowKind < 0;
  482. } //IsDAWindow
  483.  
  484.  
  485.  
  486. /*******************************************************************
  487. *    IsAppWindow    - Checks to see if a window belongs to our app
  488. *
  489. *        window        - the culprit
  490. *
  491. *        returns        - true if it's an app window
  492. *
  493. **********************************************************************/
  494. #pragma segment Main
  495. pascal Boolean IsAppWindow(WindowPtr window)
  496. {
  497.     long    theRefCon;
  498.  
  499.     // Check the userkind and the refcon for tool windows
  500.     if (window == NULL)
  501.         return FALSE;
  502.     else 
  503.     {
  504.         theRefCon = GetWRefCon(window);
  505.         return
  506.             ((((WindowPeek) window)->windowKind >= userKind) || 
  507.              (((WindowPeek) window)->windowKind == dialogKind)) &&
  508.             (gTerm != (TermHandle) theRefCon) &&
  509.             (gConn != (ConnHandle) theRefCon) &&
  510.             (gFT   != (FTHandle)   theRefCon);
  511.     }
  512. } //IsAppWindow
  513.  
  514.  
  515.  
  516. /*******************************************************************
  517. *    AlertUser    - Informs the user of any errors
  518. *
  519. *        msg        - The string to display
  520. *        fatal    - Exit if this is a fatal error
  521. *
  522. **********************************************************************/
  523. #pragma segment Main
  524. pascal void AlertUser(Str255 msg, Boolean fatal) 
  525. {
  526.     short    itemHit;
  527.     
  528.     SetCursor(&qd.arrow);
  529.     
  530.     ParamText(msg,"\p","\p","\p");
  531.     itemHit = Alert(rUserAlert, NULL);
  532.     
  533.     if (fatal)
  534.         Terminate();
  535. } // AlertUser    
  536.  
  537.  
  538.  
  539. /*******************************************************************
  540. *    OpenConnection    - Initiates a connection
  541. *
  542. **********************************************************************/
  543. #pragma segment Main
  544. pascal void OpenConnection(void) 
  545. {
  546.     CMErr            theErr;
  547.     CMBufferSizes    sizes;        // Connection Tool data        
  548.     CMStatFlags        status;
  549.     
  550.     if (gConn != NULL) 
  551.     {
  552.         // Get connection info        
  553.         theErr = CMStatus(gConn, sizes, &status);
  554.         
  555.         if (theErr == noErr) 
  556.         {
  557.             // If it isn't already open, then open it    
  558.             if ((status & (cmStatusOpen + cmStatusOpening)) == 0)
  559.                 theErr = CMOpen(gConn, FALSE, NULL, 0);
  560.         }
  561.         
  562.         if (theErr != noErr)
  563.             ;            // Conn tool will alert user on an error        
  564.     }
  565. } //OpenConnection
  566.  
  567.  
  568.  
  569. /*******************************************************************
  570. *    CloseConnection    - Kills a connection
  571. *
  572. **********************************************************************/
  573. #pragma segment Main
  574. pascal void CloseConnection(void) 
  575. {
  576.     CMErr            theErr;
  577.     CMBufferSizes    sizes;        // Connection Tool data        
  578.     CMStatFlags        status;
  579.  
  580.     // Kill the current connection    
  581.     if (gConn != NULL) 
  582.     {
  583.         theErr = CMStatus(gConn, sizes, &status);
  584.         
  585.         // If it's open, then close it    
  586.         if (theErr == noErr)
  587.             if ((status & (cmStatusOpen+ cmStatusOpening)) != 0)
  588.                 theErr = CMClose(gConn, FALSE, NULL, 0, TRUE);
  589.         
  590.         if (theErr != noErr)
  591.             ;        // Conn tool will alert user on an error        
  592.  
  593.     }
  594.     
  595. } //CloseConnection
  596.  
  597.  
  598.  
  599. /*******************************************************************
  600. *    DoCloseWindow    - Closes the window
  601. *
  602. *        window        - the culprit
  603. *
  604. *        returns        - always returns true
  605. *
  606. **********************************************************************/
  607. #pragma segment Main
  608. pascal Boolean DoCloseWindow(WindowPtr window)
  609. {
  610.     Boolean retCode = TRUE;
  611.     
  612.     if (IsDAWindow(window))
  613.         CloseDeskAcc(((WindowPeek) window)->windowKind);
  614.     else 
  615.         if (IsAppWindow(window)) 
  616.         {
  617.         
  618.             CloseConnection();            // Stop what we're doin'        
  619.             
  620.             // Dispose of all the tools    
  621.             if (gTerm != NULL) 
  622.             {    
  623.                 HUnlock((Handle) gTerm);
  624.                 TMDispose(gTerm);
  625.             }
  626.             
  627.             if (gFT != NULL) 
  628.             {
  629.                 HUnlock((Handle) gFT);
  630.                 FTDispose(gFT);
  631.             }
  632.                 
  633.             if (gConn != NULL) 
  634.             {
  635.                 HUnlock((Handle) gConn);
  636.                 CMDispose(gConn);
  637.             }
  638.                     
  639.             if (gBuffer != NULL)    // Clean up our buffer        
  640.                 DisposPtr(gBuffer);
  641.                 
  642.             DisposeWindow(window);
  643.         } // App Window    
  644.     
  645.     return retCode;
  646. } //DoCloseWindow
  647.  
  648.  
  649. /*******************************************************************
  650. *    FindToolID    - Tries to get the default tool proc id,
  651. *                otherwise, gets the first one it finds.
  652. *
  653. *        toolClass    - What kind of tool: term, ft, conn
  654. *
  655. *        returns        - the tool proc id or -1 if not found
  656. *
  657. **********************************************************************/
  658. #pragma segment Main
  659. pascal short FindToolID(OSType toolClass)
  660. {
  661.     Str255    toolName;    // tool file name        
  662.     OSErr    anyErr;
  663.     short    procID;        // tool fref number        
  664.     
  665.     procID = -1;                // Unknown tool            
  666.     
  667.     switch (toolClass)
  668.     {
  669.         case classTM:
  670.             // If it can't get the default, get the 1st    
  671.             BlockMove(kDefaultTermTool, toolName, kDefaultTermTool[0] + 1);    //VT102 Tool
  672.             procID = TMGetProcID(toolName);
  673.             
  674.             if (procID == -1) 
  675.             {
  676.                 anyErr = CRMGetIndToolName(toolClass, 1, toolName);
  677.                 if (anyErr == noErr)
  678.                     procID = TMGetProcID(toolName);
  679.             }
  680.             break;
  681.             
  682.         case classCM:
  683.             // If it can't get the default, get the 1st    
  684.             BlockMove(kDefaultConnTool, toolName, kDefaultConnTool[0] + 1);
  685.             procID = CMGetProcID(toolName);
  686.             
  687.             if (procID == -1) 
  688.             {
  689.                 anyErr = CRMGetIndToolName(toolClass,1,toolName);
  690.                 if (anyErr == noErr)
  691.                     procID = CMGetProcID(toolName);
  692.             }
  693.             break;
  694.             
  695.         case classFT: 
  696.             // If it can't get the default, get the 1st    
  697.             BlockMove(kDefaultFTTool, toolName, kDefaultFTTool[0] + 1);
  698.             procID = FTGetProcID(toolName);
  699.             
  700.             if (procID == -1) 
  701.             {
  702.                 anyErr = CRMGetIndToolName(toolClass,1,toolName);
  703.                 if (anyErr == noErr)
  704.                     procID = FTGetProcID(toolName);
  705.             }
  706.             break;
  707.     }
  708.     
  709.     return procID;
  710. } //FindToolID
  711.  
  712.  
  713. /*******************************************************************
  714. *    DoNewWindow    - Gets the window and creates the session
  715. *
  716. *        window        - the culprit
  717. *
  718. *        returns        - always returns true
  719. *
  720. **********************************************************************/
  721. #pragma segment Main
  722. pascal Boolean DoNewWindow()
  723. {
  724.     WindowPtr        window;        // the window to create            
  725.     Rect            theRect;    // for the terminal bounds        
  726.     short            procID;        // tool's ref number                
  727.     CMBufferSizes    sizes;        // requested size of the buffers    
  728.     
  729.     // Get window                        
  730.     window = GetNewWindow(rWindow, NULL, (WindowPtr) -1);
  731.     SetPort(window);    
  732.     
  733.     // TERMINAL TOOL    
  734.     procID = FindToolID(classTM);
  735.     if (procID == -1)
  736.         AlertUser("\pNo terminal tools found",TRUE);
  737.         
  738.     theRect = window->portRect;
  739.     
  740.     // Flags set to 0; no cacheProc, breakProc, or clikLoop;     
  741.     // refCon and UserData are 0.                            
  742. #ifdef THINK_C
  743.     gTerm = TMNew(&theRect, &theRect, 0, procID, window, &TermSendProc,
  744.                   NULL, NULL, NULL, &ToolGetConnEnvirons, 0, 0);
  745. #else
  746.     gTerm = TMNew(&theRect, &theRect, 0, procID, window, (TerminalSendProcPtr) &TermSendProc,
  747.                   NULL, NULL, NULL, (TerminalEnvironsProcPtr) &ToolGetConnEnvirons, 0, 0);
  748. #endif                  
  749.     if (gTerm == NULL)
  750.         AlertUser("\pCan't create a terminal tool",TRUE);
  751.     
  752.     MoveHHi((Handle) gTerm);
  753.     HLock((Handle) gTerm);
  754.     
  755.     // CONNECTION TOOL    
  756.     procID = FindToolID(classCM);
  757.     if (procID == -1)
  758.         AlertUser("\pNo connection tools found",TRUE);
  759.     
  760.     sizes[cmDataIn] = kBufferSize;
  761.     sizes[cmDataOut] = kBufferSize;
  762.     sizes[cmCntlIn] = 0;
  763.     sizes[cmCntlOut] = 0;
  764.     sizes[cmAttnIn] = 0;
  765.     sizes[cmAttnOut] = 0;
  766.     
  767.     // refCon and UserData are 0. 
  768.     gConn = CMNew(procID, cmData, sizes, 0, 0);
  769.     if (gConn == NULL)
  770.         AlertUser("\pCan't create a connection tool",TRUE);
  771.         
  772.     MoveHHi((Handle) gConn);
  773.     HLock((Handle) gConn);
  774.     
  775.     // Allocate space for the read/writes using the number    
  776.     // returned by the connection tool                        
  777.     gBuffer = NewPtr((*gConn)->bufSizes[cmDataIn]);
  778.     if (MemError() != noErr)
  779.         AlertUser("\pOut of memory",TRUE);
  780.     
  781.     // FILE TRANSFER TOOL    
  782.     procID = FindToolID(classFT);
  783.     if (procID == -1)
  784.         AlertUser("\pNo file transfer tools found",FALSE);
  785.     
  786.     // Flags set to 0, no read/write proc (let the tool use its own),
  787.     // refCon and UserData are 0. 
  788. #ifdef THINK_C                                    
  789.     gFT = FTNew(procID, 0, &FTSendProc, &FTReceiveProc, NULL, NULL, 
  790.                 &ToolGetConnEnvirons, window, 0, 0);
  791. #else
  792.     gFT = FTNew(procID, 0, (FileTransferSendProcPtr) &FTSendProc, 
  793.                 (FileTransferReceiveProcPtr)  &FTReceiveProc, NULL, NULL, 
  794.                 (FileTransferEnvironsProcPtr) &ToolGetConnEnvirons, window, 0, 0);
  795. #endif
  796.     if (gFT == NULL)
  797.         AlertUser("\pCan't create a file transfer tool",TRUE);
  798.         
  799.     MoveHHi((Handle) gFT);
  800.     HLock((Handle) gFT);
  801.     
  802.     gWasFT = FALSE;            // FT in progress                    
  803.     gStartFT = FALSE;            // Auto-received string found        
  804.     gFTSearchRefNum = 0;        // Clear the search refnum            
  805.                 
  806.     AddFTSearch();                // Look for the auto-receive string    
  807.     
  808.     return TRUE;        
  809. } //DoNewWindow
  810.  
  811.  
  812.  
  813. /*******************************************************************
  814. *    Initialize        - Inits the various toolbox stuff
  815. *
  816. **********************************************************************/
  817.  
  818. #pragma segment Initialize
  819. pascal void Initialize(void)
  820. {
  821.     Handle        menuBar;
  822.     OSErr        ignoreError;
  823.     long        total, contig;
  824.     Boolean        ignoreResult;
  825.     EventRecord    event;
  826.     short        count;
  827.     SysEnvRec    terraMac;    //set up by Initialize
  828.     short        err;
  829.  
  830.     // Do we have Multifinder?    
  831.     gHasWaitNextEvent = TrapAvailable(_WaitNextEvent, ToolTrap);
  832.     gInBackground = FALSE;
  833.  
  834.     // Standard Fare        
  835.     InitGraf(&qd.thePort);
  836.     InitFonts();
  837.     InitWindows();
  838.     InitMenus();
  839.     TEInit();
  840.     InitDialogs(NULL);
  841.     InitCursor();
  842.     
  843.     // Bring us to the front        
  844.     for (count = 1; count <= 3; count++)
  845.         ignoreResult = GetNextEvent(everyEvent, &event);
  846.     
  847.     // Does CommToolbox Exist?    
  848.     if (!TrapAvailable(_CommToolboxTrap, OSTrap))
  849.         AlertUser("\pACK!! No CommToolbox",TRUE);
  850.     
  851.     // Check for System 6.0 or better, 64K ROM    
  852.     ignoreError = SysEnvirons(kSysEnvironsVersion, &terraMac);
  853.     
  854.     if ((terraMac.systemVersion < 0x0600) || (terraMac.machineType < 0)) 
  855.             AlertUser("\pNeed System 6.0 or better",TRUE);
  856.      
  857.     // Check various memory configs                
  858.     if (FreeMem() < kMinHeap) 
  859.         AlertUser("\pOut of Memory",TRUE);
  860.     
  861.     PurgeSpace(&total, &contig);
  862.     if (total < kMinSpace) 
  863.         AlertUser("\pOut of Memory",TRUE);
  864.     
  865.     // Load up the Communications Toolbox        
  866.     // Must Initialize CRM && CTBUtilities first    
  867.     err =     InitCTBUtilities();
  868.     err =     InitCRM();
  869.  
  870.     err = InitTM();    // initializes the Terminal Manager 
  871.     if (err == tmNoTools)
  872.         AlertUser("\pNo terminal tools found",TRUE);
  873.     
  874.     err =     InitCM();    // initializes the Connection Manager 
  875.     if (err == cmNoTools)
  876.         AlertUser("\pNo connection tools found",TRUE);
  877.     
  878.     err =     InitFT();    // initializes the File Transfer Manager 
  879.     if (err == ftNoTools)
  880.         AlertUser("\pNo file transfer tools found",FALSE);
  881.         
  882.     gTerm = NULL;
  883.     gConn = NULL;
  884.     gFT = NULL;
  885.     gFTSearchRefNum = 0;
  886.     
  887.     if (!DoNewWindow())
  888.         AlertUser("\pCan't create a session",TRUE);
  889.  
  890.     menuBar = GetNewMBar(rMenuBar);        //read menus into menu bar
  891.     if (menuBar == NULL) 
  892.         AlertUser("\pCan't get the menu bar",TRUE);
  893.     SetMenuBar(menuBar);                    //install menus
  894.     DisposHandle(menuBar);
  895.     
  896.     AddResMenu(GetMHandle(mApple), 'DRVR');    //add DA names to Apple menu
  897.     DrawMenuBar();
  898. } //
  899.  
  900.  
  901. /*******************************************************************
  902. *    Terminate        - Cleans up and exits
  903. *
  904. **********************************************************************/
  905.  
  906. #pragma segment Main
  907. pascal void Terminate(void)
  908. {
  909.     WindowPtr     aWindow;        // the window to shut        
  910.     Boolean        closed;            // Are we done, yet            
  911.  
  912.     // Close all the open windows    
  913.     closed = TRUE;
  914.  
  915.     aWindow = FrontWindow();    
  916.     
  917.     do {        
  918.         if (aWindow != NULL)
  919.             if (IsAppWindow(aWindow))
  920.                 closed = DoCloseWindow(aWindow);
  921.                 
  922.         // Try the next window    
  923.         if (aWindow != NULL)
  924.             aWindow = (WindowPtr) ((WindowPeek) aWindow)->nextWindow; 
  925.         
  926.     } while (closed && (aWindow != NULL));
  927.     
  928.     if (closed)
  929.         ExitToShell();                            //exit if no cancellation
  930. } //Terminate
  931.  
  932.  
  933.  
  934. /*******************************************************************
  935. *    AdjustMenus        - Enables && Disables items based on current state
  936. *
  937. **********************************************************************/
  938.  
  939. #pragma segment Main
  940. pascal void AdjustMenus(void)
  941. {
  942.     WindowPtr        window;        // whose in front            
  943.     MenuHandle        menu;        // the menu to manipulate    
  944.     CMErr            theErr;
  945.     CMBufferSizes    sizes;        // Connection tool data        
  946.     CMStatFlags        status;
  947.  
  948.     window = FrontWindow();
  949.  
  950.     menu = GetMHandle(mFile);
  951.     if (menu == NULL)
  952.         AlertUser("\pCan't get menu resource", TRUE);
  953.         
  954.     if (gConn != NULL) 
  955.     {
  956.         theErr = CMStatus(gConn, sizes, &status);
  957.         if (theErr == noErr) 
  958.         {
  959.             if (!IsDAWindow(window)) 
  960.             {
  961.                 SetItem(menu,iOpen,"\pOpen Connection");
  962.                 SetItem(menu,iClose,"\pClose Connection");
  963.                 
  964.                 // Let the menu show the proper state of the union    
  965.                 if ((status & (cmStatusOpen+ cmStatusOpening)) == 0) 
  966.                 {
  967.                     EnableItem(menu, iOpen);
  968.                     DisableItem(menu, iClose);
  969.                 }                
  970.                 else 
  971.                 {
  972.                     DisableItem(menu, iOpen);
  973.                     EnableItem(menu, iClose);
  974.                 }
  975.                 
  976.                 // Check state of the FT tool to Enable send/receive    
  977.                 DisableItem(menu,iSendFile);
  978.                 DisableItem(menu,iReceiveFile);
  979.                 
  980.                 if (gFT != NULL)
  981.                 {
  982.                     if (((*gFT)->attributes & ftSendDisable) == 0)
  983.                         EnableItem(menu,iSendFile);
  984.                         
  985.                     if (((*gFT)->attributes & ftReceiveDisable) == 0)
  986.                         EnableItem(menu,iReceiveFile);                    
  987.                 }
  988.             }            
  989.             else 
  990.             {
  991.                 // Set for desk accesories    
  992.                 SetItem(menu,iOpen,"\pOpen");
  993.                 SetItem(menu,iClose,"\pClose");
  994.                 DisableItem(menu, iOpen);
  995.                 EnableItem(menu,iClose);
  996.                 DisableItem(menu,iSendFile);
  997.                 DisableItem(menu,iReceiveFile);
  998.             }
  999.             
  1000.         } // good status    
  1001.     } // good connection    
  1002.     
  1003.     
  1004.     menu = GetMHandle(mEdit);
  1005.     if (menu == NULL)
  1006.         AlertUser("\pCan't get menu resource", TRUE);
  1007.     
  1008.     if (IsDAWindow(window)) 
  1009.     {    // DAs might use this menu    
  1010.         EnableItem(menu, iUndo);
  1011.         EnableItem(menu, iCut);
  1012.         EnableItem(menu, iCopy);
  1013.         EnableItem(menu, iPaste);
  1014.         EnableItem(menu, iClear);
  1015.     }
  1016.     else 
  1017.     {    // but we don't use it yet    
  1018.         DisableItem(menu, iUndo);
  1019.         DisableItem(menu, iCut);
  1020.         DisableItem(menu, iCopy);
  1021.         DisableItem(menu, iClear);
  1022.         DisableItem(menu, iPaste);
  1023.     }
  1024.  
  1025.     menu = GetMHandle(mSettings);
  1026.     if (menu == NULL)
  1027.         AlertUser("\pCan't get menu resource", TRUE);
  1028.         
  1029.     if (!IsDAWindow(window)) 
  1030.     {        
  1031.         // Enable if we're front    
  1032.         EnableItem(menu, iConnection);
  1033.         EnableItem(menu, iFileTransfer);
  1034.         EnableItem(menu, iTerminal);
  1035.     }
  1036.     else 
  1037.     {
  1038.         DisableItem(menu, iConnection);
  1039.         DisableItem(menu, iFileTransfer);
  1040.         DisableItem(menu, iTerminal);
  1041.     }
  1042.     
  1043. } //AdjustMenus
  1044.  
  1045.  
  1046. /*******************************************************************
  1047. *    DoToolMenu        - Tries to give the menu to the tool
  1048. *
  1049. *        menuID        - the menu info from DoMenuCommand
  1050. *        menuItem
  1051. *
  1052. *        returns        - TRUE if a tool handled the menu
  1053. *
  1054. **********************************************************************/
  1055. #pragma segment Main
  1056. pascal Boolean DoToolMenu(int menuID, int menuItem)
  1057. {
  1058.     if (gTerm != NULL)
  1059.         if (TMMenu(gTerm, menuID, menuItem)) 
  1060.             return TRUE;
  1061.  
  1062.     if (gConn != NULL)
  1063.         if (CMMenu(gConn, menuID, menuItem)) 
  1064.             return TRUE;
  1065.     
  1066.     if (gFT != NULL)
  1067.         if (FTMenu(gFT, menuID, menuItem))
  1068.             return TRUE;
  1069.         
  1070.     return FALSE;    
  1071. } //DoToolMenu
  1072.  
  1073.  
  1074. /*******************************************************************
  1075. *    DoMenuCommand    - Executes a menu command
  1076. *
  1077. *        menuResult    - the menu id and item number
  1078. *
  1079. **********************************************************************/
  1080.  
  1081. #pragma segment Main
  1082. pascal void DoMenuCommand(long menuResult)
  1083. {
  1084.     short    menuID;            // resource ID of the selected menu    
  1085.     short    menuItem;        // item number of the selected menu    
  1086.     short    itemHit;        // for the alert                        
  1087.     Str255    daName;            // for opening desk accesories        
  1088.     short    daRefNum;
  1089.     Boolean    handledByDA;    // DA edit menu handling                
  1090.     Boolean    ignore;        
  1091.     Point    where;            // For choose dialog                    
  1092.     short    result;
  1093.  
  1094.     menuID = HiWord(menuResult);    //use built-ins (for efficiency)...
  1095.     menuItem = LoWord(menuResult);    //to get menu item number and menu number
  1096.     
  1097.     // First see if the menu belonged to a tool    
  1098.         
  1099.     if (!DoToolMenu(menuID,menuItem))
  1100.         switch (menuID) 
  1101.         {
  1102.             case mApple:
  1103.                 switch (menuItem) 
  1104.                 {
  1105.                     case iAbout:                
  1106.                         //bring up alert for About
  1107.                         itemHit = Alert(rAboutAlert, NULL);
  1108.                         break;
  1109.                         
  1110.                     default: 
  1111.                         // all non-About items in this menu are DAs
  1112.                         GetItem(GetMHandle(mApple), menuItem, daName);
  1113.                         daRefNum = OpenDeskAcc(daName);
  1114.                         break;
  1115.                 }     
  1116.                 
  1117.             case mFile:
  1118.                 switch (menuItem) 
  1119.                 {
  1120.                     case iOpen:
  1121.                         if (!IsDAWindow(FrontWindow()))
  1122.                             OpenConnection();
  1123.                         break;
  1124.                         
  1125.                     case iClose:
  1126.                         if (IsDAWindow(FrontWindow()))
  1127.                             ignore = DoCloseWindow(FrontWindow());
  1128.                         else
  1129.                             CloseConnection();
  1130.                         break;
  1131.                         
  1132.                     case iSendFile:
  1133.                         if (!IsDAWindow(FrontWindow()))
  1134.                             DoSend();
  1135.                         break;
  1136.                         
  1137.                     case iReceiveFile:
  1138.                         if (!IsDAWindow(FrontWindow()))
  1139.                             DoReceive();
  1140.                         break;
  1141.                         
  1142.                     case iQuit:
  1143.                         Terminate();
  1144.                         break;
  1145.                 }     
  1146.                 
  1147.             case mEdit:                        
  1148.                 //call SystemEdit for DA editing && MultiFinder
  1149.                 //since we don't do any editing
  1150.                 handledByDA = SystemEdit(menuItem-1);    
  1151.                 break;
  1152.                 
  1153.             case mSettings:
  1154.                 switch (menuItem) 
  1155.                 {
  1156.                     case iConnection:
  1157.                         if (gConn != NULL) 
  1158.                         {
  1159.                             HUnlock((Handle) gConn);
  1160.                             
  1161.                             SetPt(&where,10,40);
  1162.  
  1163.                             result = CMChoose(&gConn, where, NULL);
  1164.  
  1165.                             switch (result) 
  1166.                             {
  1167.                                 case chooseDisaster:
  1168.                                 case chooseFailed:
  1169.                                     AlertUser("\pConnection choose failed",
  1170.                                               (result == chooseDisaster));
  1171.                                     break;
  1172.                                 case chooseOKMajor: 
  1173.                                     AddFTSearch();
  1174.                                     break;
  1175.                             }
  1176.                             
  1177.                             HLock((Handle) gConn);
  1178.                         }     
  1179.                         break;
  1180.                         
  1181.                     case iFileTransfer:
  1182.                         if (gFT != NULL) 
  1183.                         {
  1184.                             HUnlock((Handle) gFT);
  1185.                             
  1186.                             SetPt(&where,10,40);
  1187.                             result = FTChoose(&gFT, where, NULL);
  1188.                             
  1189.                             switch (result) 
  1190.                             {
  1191.                                 case chooseDisaster:
  1192.                                 case chooseFailed:
  1193.                                     AlertUser("\pFile Transfer choose failed", 
  1194.                                               (result == chooseDisaster));
  1195.                                     break;
  1196.                                 case chooseOKMinor:
  1197.                                 case chooseOKMajor: 
  1198.                                     // Get rid of the old search            
  1199.                                     if ((gFTSearchRefNum != 0) && (gConn != NULL))
  1200.                                         CMRemoveSearch(gConn,gFTSearchRefNum);
  1201.                                     gFTSearchRefNum = 0;
  1202.                                     
  1203.                                     AddFTSearch();    // Add the new FT tool search    
  1204.                                     break;
  1205.                             }
  1206.                             
  1207.                             HLock((Handle) gFT);
  1208.                         } // good ft    
  1209.                         break;
  1210.                         
  1211.                     case iTerminal: 
  1212.                         if (gTerm != NULL) 
  1213.                         {
  1214.                             HUnlock((Handle) gTerm);
  1215.                             
  1216.                             SetPt(&where,10,40);
  1217.                             result = TMChoose(&gTerm, where, NULL);
  1218.                             
  1219.                             if ((result < 0))
  1220.                                 AlertUser("\pTerminal choose failed",(result == chooseDisaster));
  1221.                             
  1222.                             HLock((Handle) gTerm);
  1223.                         } 
  1224.                         break;
  1225.                         
  1226.                 } // case    menuitem    
  1227.                     
  1228.         } // case menuid    
  1229.     
  1230.     HiliteMenu(0);                    //unhighlight what MenuSelect (or MenuKey) hilited
  1231. } //DoMenuCommand
  1232.  
  1233.  
  1234. /*******************************************************************
  1235. *    DoUpdate    - Updates the window
  1236. *
  1237. *        window    - target of teh update
  1238. *
  1239. **********************************************************************/
  1240. #pragma segment Main
  1241. pascal void DoUpdate(WindowPtr window)
  1242. {
  1243.     RgnHandle    savedClip;        // saved info for reset later    
  1244.     GrafPtr        savedPort;
  1245.     
  1246.     if (IsAppWindow(window)) 
  1247.     {
  1248.         GetPort(&savedPort);
  1249.         SetPort(window);
  1250.         
  1251.         // Clip to the window content    
  1252.         savedClip = NewRgn();
  1253.         GetClip(savedClip);
  1254.         ClipRect(&window->portRect);
  1255.         
  1256.         BeginUpdate(window);
  1257.             if (gTerm != NULL)    // Update the terminal tool        
  1258.                 TMUpdate(gTerm, window->visRgn);
  1259.         EndUpdate(window);
  1260.         
  1261.         SetClip(savedClip);
  1262.         DisposeRgn(savedClip);
  1263.         
  1264.         SetPort(savedPort);
  1265.     }
  1266. } //DoUpdate
  1267.  
  1268.  
  1269. /*******************************************************************
  1270. *    DoResume    - Suspends/Resumes the window
  1271. *
  1272. *        becomingActive    - Resume or Suspend
  1273. *
  1274. **********************************************************************/
  1275.  
  1276. #pragma segment Main
  1277. pascal void DoResume(Boolean becomingActive)
  1278. {
  1279.     WindowPtr    theWindow;
  1280.     GrafPtr        savedPort;
  1281.     
  1282.     // Since the front window could be a tool window, we need    
  1283.     // to find the app window by walking the list so we can        
  1284.     // send resume messages to the tools                            
  1285.     
  1286.     GetPort(&savedPort);
  1287.     
  1288.     theWindow = FrontWindow();
  1289.     
  1290.     while (theWindow != NULL)
  1291.     {
  1292.         if (IsAppWindow(theWindow)) 
  1293.         {
  1294.             SetPort(theWindow);
  1295.         
  1296.             /* Tools need to adjust their menus, text selection, etc    */            
  1297.             if (gTerm != NULL)
  1298.                 TMResume(gTerm, becomingActive);
  1299.             
  1300.             if (gConn != NULL)
  1301.                 CMResume(gConn, becomingActive);
  1302.         
  1303.             if (gFT != NULL)
  1304.                 FTResume(gFT, becomingActive);
  1305.         } // app window    
  1306.         
  1307.         // Try the next window    
  1308.         theWindow = (WindowPtr) ((WindowPeek) theWindow)->nextWindow;
  1309.     }
  1310.     
  1311.     SetPort(savedPort);
  1312.     
  1313. } //DoResume
  1314.  
  1315.  
  1316. /*******************************************************************
  1317. *    DoActivate    - (De)Activates the window
  1318. *
  1319. *        window            - target of the update
  1320. *        becomingActive    - Activate or Deactivate
  1321. *
  1322. **********************************************************************/
  1323.  
  1324. #pragma segment Main
  1325. pascal void DoActivate(WindowPtr window, Boolean becomingActive)
  1326. {
  1327.     if (IsAppWindow(window)) 
  1328.     {
  1329.         SetPort(window);
  1330.     
  1331.         /* Tools need to adjust their menus, text selection, etc    */            
  1332.         if (gTerm != NULL)
  1333.             TMActivate(gTerm, becomingActive);
  1334.         
  1335.         if (gConn != NULL)
  1336.             CMActivate(gConn, becomingActive);
  1337.     
  1338.         if (gFT != NULL)
  1339.             FTActivate(gFT, becomingActive);
  1340.     }
  1341.     
  1342. } //DoActivate
  1343.  
  1344.  
  1345. /*******************************************************************
  1346. *    AdjustCursor    - Updates mouse cursor depending on location
  1347. *
  1348. *        mouse        - the location of the mouse (global coords)
  1349. *
  1350. **********************************************************************/
  1351. #pragma segment Main
  1352. pascal void AdjustCursor(Point mouse)
  1353. {
  1354.     WindowPtr    window;
  1355.  
  1356.     window = FrontWindow();        // Adjust only if front            
  1357.     
  1358.     if ((!gInBackground) && (IsAppWindow(window))) 
  1359.     {
  1360.         GlobalToLocal(&mouse);
  1361.         
  1362.         // If it's outside the content, set to arrow        
  1363.         // otherwise the terminal tool will  handle it    
  1364.         
  1365.         if (gTerm != NULL)
  1366.             if (!PtInRect(mouse,&((*gTerm)->viewRect)))
  1367.                 InitCursor();
  1368.                 
  1369.     } // app window    
  1370.     
  1371. } //AdjustCursor
  1372.  
  1373.  
  1374. /*******************************************************************
  1375. *    DoToolEvent        - Tries to pass the event to a tool if the 
  1376. *                    window is a tool window
  1377. *
  1378. *        event        - the event received
  1379. *
  1380. *        returns        - True if the tool handled it
  1381. *
  1382. **********************************************************************/
  1383. #pragma segment Main
  1384. pascal Boolean DoToolEvent(EventRecord event, WindowPtr window)
  1385. {
  1386.     Boolean retCode;
  1387.     
  1388.     if (window != NULL)
  1389.     {
  1390.         retCode = TRUE;
  1391.         
  1392.         if ((gFT != NULL) && (gFT == (FTHandle) GetWRefCon(window)))
  1393.             FTEvent(gFT, &event);
  1394.         else 
  1395.             if ((gConn != NULL) &&  (gConn == (ConnHandle) GetWRefCon(window)))
  1396.                 CMEvent(gConn, &event);
  1397.             else 
  1398.                 if ((gTerm != NULL) && (gTerm == (TermHandle) GetWRefCon(window)))
  1399.                     TMEvent(gTerm, &event);
  1400.                 else
  1401.                     retCode = FALSE;
  1402.     }    
  1403.     else
  1404.         retCode = FALSE;
  1405.         
  1406.     return retCode;
  1407. } //DoToolEvent
  1408.  
  1409.  
  1410.  
  1411. /*******************************************************************
  1412. *    DoEvent    - Updates mouse cursor depending on location
  1413. *
  1414. *        event    - the event to handle
  1415. *
  1416. **********************************************************************/
  1417. #pragma segment Main
  1418. pascal void DoEvent(EventRecord event)
  1419. {
  1420.     int            part;            // where the mouse click was    
  1421.     short        err;
  1422.     WindowPtr    window;            // the click's window        
  1423.     char        key;            // the letter typed            
  1424.     Point        aPoint;            // for the dialog top left    
  1425.     long        result;            // result from MenuKey        
  1426.     Boolean        processed;        // Did the App handle it        
  1427.  
  1428.     switch (event.what)
  1429.     {
  1430.         case mouseDown: 
  1431.             part = FindWindow(event.where, &window);
  1432.  
  1433.             switch (part) 
  1434.             {
  1435.                 case inMenuBar:         //process the menu command    
  1436.                     AdjustMenus();
  1437.                     DoMenuCommand(MenuSelect(event.where));
  1438.                     break;
  1439.                 
  1440.                 case inSysWindow:                //let the system handle the mouseDown
  1441.                     SystemClick(&event, window);
  1442.                     break;
  1443.                     
  1444.                 case inContent:
  1445.                     // The terminal tool needs to handle selections    
  1446.                     if (!DoToolEvent(event,window)) 
  1447.                     {
  1448.                         if (window != FrontWindow())
  1449.                             SelectWindow(window);
  1450.                         else 
  1451.                             if (gTerm != NULL)
  1452.                                 TMClick(gTerm, &event);
  1453.                     }
  1454.                     break;
  1455.                     
  1456.                 case inDrag:        //pass screenBits.bounds to get all gDevices
  1457.                     if (!DoToolEvent(event,window))
  1458.                         DragWindow(window, event.where, &qd.screenBits.bounds);
  1459.                     break;
  1460.                     
  1461.                 case inGrow:
  1462.                 case inZoomIn:
  1463.                 case inZoomOut:
  1464.                 case inGoAway:
  1465.                     DoToolEvent(event,window);
  1466.                     break;
  1467.             }
  1468.             break; // case mouseDown
  1469.                         
  1470.         case keyDown:
  1471.         case autoKey:         //check for menukey equivalents
  1472.             window = FrontWindow();
  1473.             
  1474.             // Get the key    
  1475.             key = event.message & charCodeMask;
  1476.             processed = FALSE;
  1477.             
  1478.             // The terminal tool might be mapping the cmd key     
  1479.             // so if menukey fails, send it to the tool            
  1480.             
  1481.             if (((event.modifiers) & cmdKey) != 0) 
  1482.             {
  1483.                 AdjustMenus();            //enable/disable/check menu items properly
  1484.                 result = MenuKey(key);
  1485.                 if (result != 0) {
  1486.                     processed = TRUE;
  1487.                     DoMenuCommand(result);
  1488.                 }
  1489.             }
  1490.             
  1491.             if ((gTerm != NULL) && !processed)
  1492.                 if (!DoToolEvent(event, window))
  1493.                     TMKey(gTerm, &event);            
  1494.             break;
  1495.         
  1496.         case activateEvt: 
  1497.             window = (WindowPtr) event.message;
  1498.             
  1499.             if (!DoToolEvent(event,window))
  1500.                 DoActivate(window, ((event.modifiers) & activeFlag) != 0);
  1501.             break;
  1502.         
  1503.         case updateEvt: 
  1504.             window = (WindowPtr) event.message;
  1505.             
  1506.             if (!DoToolEvent(event,window))
  1507.                 DoUpdate(window);
  1508.             break;
  1509.         
  1510.         case diskEvt:
  1511.             if (HiWord(event.message) != noErr) 
  1512.             {
  1513.                 SetPt(&aPoint, kDILeft, kDITop);
  1514.                 err = DIBadMount(aPoint, event.message);
  1515.             }
  1516.             break;
  1517.             
  1518.         case kOSEvent:
  1519.             // Send to frontmost tool window && all tools    
  1520.             // as this is an application-wide event            
  1521.             
  1522.             switch((event.message >> 8) & 0xFF)     //high byte of message
  1523.             {
  1524.                 case kSuspendResumeMessage:
  1525.                     DoToolEvent(event,FrontWindow());
  1526.                     gInBackground = ((event.message & kResumeMask) == 0);
  1527.                     DoResume(!gInBackground);
  1528.                     break;
  1529.             }
  1530.             break;
  1531.     }
  1532. } //DoEvent
  1533.  
  1534.  
  1535. /*******************************************************************
  1536. *    DoIdle    - Idles all the tools
  1537. *
  1538. **********************************************************************/
  1539. #pragma segment Main
  1540. pascal void DoIdle(void)
  1541. {
  1542.     WindowPtr        theWindow;                // The target to idle        
  1543.     Boolean            doFT;                    // route data to FT Tool        
  1544.     Boolean            doTM;                    // route data to Term Tool    
  1545.     GrafPtr            savedPort;                // for later reset            
  1546.  
  1547.     GetPort(&savedPort);                        // Save for later            
  1548.     theWindow = FrontWindow();                // Gimme the first one        
  1549.     
  1550.     // Give idle time for the window    
  1551.     while (theWindow != NULL)
  1552.     {
  1553.         if (IsAppWindow(theWindow)) 
  1554.         {
  1555.             SetPort(theWindow);                    // Focus on it                
  1556.             
  1557.             if (gConn != NULL)             // Give time to the connection    
  1558.                 CMIdle(gConn);
  1559.                 
  1560.             doFT = FALSE;                    // Send data to FT tool            
  1561.             doTM = TRUE;                    // Send data to terminal tool    
  1562.             
  1563.             if (gFT != NULL) 
  1564.             {
  1565.                 // Is there a file transfer in progress ??    
  1566.                 if ((((*gFT)->flags) & ftIsFTMode) != 0) 
  1567.                 {
  1568.                     doFT = TRUE;
  1569.                     gWasFT = TRUE;
  1570.                     
  1571.                     // If the FT tool uses my connection then    
  1572.                     // don't route data to the terminal tool        
  1573.                     
  1574.                     if ((((*gFT)->attributes) & ftSameCircuit) != 0) 
  1575.                         doTM = FALSE;
  1576.                 }    // In progress    
  1577.                 else 
  1578.                 {
  1579.                     if (gWasFT) 
  1580.                     {
  1581.                         // FT no longer in progress        
  1582.                         gWasFT = FALSE;
  1583.                         
  1584.                         // FT tool will alert the user    
  1585.                         if (((*gFT)->flags & ftSucc) == 0)
  1586.                             ;
  1587.                         
  1588.                         // The old search was removed for the transfer    
  1589.                         // so we need to re-add it here                    
  1590.                         AddFTSearch();
  1591.                     }
  1592.                                         
  1593.                     // AutoReceive string was received ?    
  1594.                     if (gStartFT)
  1595.                         DoReceive();
  1596.                 } // No FT in progress    
  1597.                 
  1598.                 if (doFT)            // Give time to FT tool                
  1599.                     FTExec(gFT);
  1600.             } // Good FT Handle    
  1601.                                 
  1602.             if (gTerm != NULL) 
  1603.             {
  1604.                 TMIdle(gTerm);                    // So it can blink its cursor, etc    
  1605.                 
  1606.                 if (doTM)        
  1607.                     TermRecvProc();                // Send Data to the terminal            
  1608.             } // Good Terminal    
  1609.             
  1610.         } // App Window    
  1611.         
  1612.         // Try the next window    
  1613.         theWindow = (WindowPtr) ((WindowPeek) theWindow)->nextWindow;
  1614.             
  1615.     } // while each window    
  1616.             
  1617.     SetPort(savedPort);                        // Back to the way it was        
  1618.         
  1619. } // DoIdle    
  1620.  
  1621.  
  1622. /*******************************************************************
  1623.  *    EventLoop    - The main event loop 
  1624.  *
  1625.  *******************************************************************/
  1626. #pragma segment Main
  1627. pascal void EventLoop(void)
  1628. {
  1629.     Boolean        gotEvent;
  1630.     EventRecord    event;
  1631.  
  1632.     //loop forever; we quit through an ExitToShell
  1633.     while (TRUE)    
  1634.     {
  1635.         DoIdle();
  1636.         
  1637.         if (gHasWaitNextEvent)     // put us 'asleep' forever under MultiFinder    
  1638.             gotEvent = WaitNextEvent(everyEvent, &event, 0, NULL);
  1639.         else 
  1640.         {
  1641.             SystemTask();                // must be called if using GetNextEvent        
  1642.             gotEvent = GetNextEvent(everyEvent, &event);
  1643.         }
  1644.         
  1645.         if (gotEvent) 
  1646.         {
  1647.             AdjustCursor(event.where);             //make sure we have the right cursor
  1648.             DoEvent(event);
  1649.         }
  1650.         
  1651.         AdjustCursor(event.where);
  1652.     }                
  1653. } //EventLoop
  1654.  
  1655.  
  1656. #pragma segment Main
  1657. main()
  1658.     MaxApplZone();            // expand the heap so code segments load at the top    
  1659.     Initialize();            // initialize the program                            
  1660.     EventLoop();            // call the main event loop                            
  1661. }
  1662.